#include <cassert>
#include "server.h"
#include "ScanOperationNode.h"
#include "Column.h"
#include "config.h"
#include "types.h"

ScanOperationNode::ScanOperationNode(const SharedArray<Type>& types, const SharedArray<int>& columns, Server* server):
		_types(types), _columns(columns), _server(server) {
	assert(types.size() == columns.size());
}

template <typename T>
int pullDataFromServer(Server* server, int column, int amount, SharedArray<T>& input);

template <>
int pullDataFromServer<int32_t>(Server* server, int column, int amount, SharedArray<int32_t>& input) {
	return server->GetInts(column, amount, input.data());
}

template <>
int pullDataFromServer<double>(Server* server, int column, int amount, SharedArray<double>& input) {
	return server->GetDoubles(column, amount, input.data());
}

template <>
int pullDataFromServer<bool>(Server* server, int column, int amount, SharedArray<bool>& input) {
	return server->GetByteBools(column, amount, input.data());
}

template <typename T>
Column pullColumnFromServer(Server* server, int column, int amount) {
	SharedArray<T> input(amount);
	int pulled = pullDataFromServer(server, column, amount, input);
	input.shrink(pulled);
	return Column(input);
}

SharedArray<Column> ScanOperationNode::pull() {
	SharedArray<Column> out(_columns.size());

	for (int i = 0; i < _columns.size(); ++i) {
		switch (_types[i]) {
			case INT:
					out[i] = pullColumnFromServer<int32_t>(_server, _columns[i], PULL_AMOUNT);
					break;

			case DOUBLE:
					out[i] = pullColumnFromServer<double>(_server, _columns[i], PULL_AMOUNT);
					break;

			case BOOL:
					out[i] = pullColumnFromServer<bool>(_server, _columns[i], PULL_AMOUNT);
					break;

			default:
				assert(false);
		}
	}

	return out;
}
